//*****************************************************************************
//
// usb_dev_msc.c - Main routines for the device mass storage class example.
//
// Copyright (c) 2012 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 9453 of the EK-LM4F232 Firmware Package.
//
//*****************************************************************************

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/usb.h"
#include "driverlib/gpio.h"
#include "driverlib/udma.h"
#include "driverlib/pin_map.h"
#include "usblib/usblib.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdmsc.h"
#include "usb_msc_structs.h"
#include "third_party/fatfs/src/diskio.h"
#include "third_party/fatfs/src/ff.h"
#include "ssidac.h"
#include "drivers/wavfile.h"

void openConfig(FIL *fp);
FATFS FatFS;
tWavFile *wavdata;
tWavHeader *wavheader;
tBoolean dummy;
unsigned char bufferWav[100] = {0};
unsigned long g_ulFlags;
unsigned long g_ulIdleTimeout;

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>USB MSC Device (usb_dev_msc)</h1>
//!
//! This example application turns the evaluation board into a USB mass storage
//! class device.  The application will use the microSD card for the storage
//! media for the mass storage device.  The screen will display the current
//! action occurring on the device ranging from disconnected, no media, reading,
//! writing and idle.
//
//*****************************************************************************

//*****************************************************************************
//
// These defines are used to define the screen constraints to the application.
//
//*****************************************************************************

//*****************************************************************************
//
// The number of ticks to wait before falling back to the idle state.  Since
// the tick rate is 100Hz this is approximately 3 seconds.
//
//*****************************************************************************
#define USBMSC_ACTIVITY_TIMEOUT 300

//*****************************************************************************
//
// This enumeration holds the various states that the device can be in during
// normal operation.
//
//*****************************************************************************
volatile enum {
	//
	// Unconfigured.
	//
	MSC_DEV_DISCONNECTED,

	//
	// Connected but not yet fully enumerated.
	//
	MSC_DEV_CONNECTED,

	//
	// Connected and fully enumerated but not currently handling a command.
	//
	MSC_DEV_IDLE,

	//
	// Currently reading the SD card.
	//
	MSC_DEV_READ,

	//
	// Currently writing the SD card.
	//
	MSC_DEV_WRITE,
} g_eMSCState;



//******************************************************************************
//
// The DMA control structure table.
//
//******************************************************************************
#ifdef ewarm
#pragma data_alignment=1024
tDMAControlTable sDMAControlTable[64];
#elif defined(ccs)
#pragma DATA_ALIGN(sDMAControlTable, 1024)
tDMAControlTable sDMAControlTable[64];
#else
tDMAControlTable sDMAControlTable[64] __attribute__ ((aligned(1024)));
#endif

//*****************************************************************************
//
// Handles bulk driver notifications related to the receive channel (data from
// the USB host).
//
// \param pvCBData is the client-supplied callback pointer for this channel.
// \param ulEvent identifies the event we are being notified about.
// \param ulMsgValue is an event-specific value.
// \param pvMsgData is an event-specific pointer.
//
// This function is called by the bulk driver to notify us of any events
// related to operation of the receive data channel (the OUT channel carrying
// data from the USB host).
//
// \return The return value is event-specific.
//
//*****************************************************************************
unsigned long RxHandler(void *pvCBData, unsigned long ulEvent,
		unsigned long ulMsgValue, void *pvMsgData) {
	return (0);
}

//*****************************************************************************
//
// Handles bulk driver notifications related to the transmit channel (data to
// the USB host).
//
// \param pvCBData is the client-supplied callback pointer for this channel.
// \param ulEvent identifies the event we are being notified about.
// \param ulMsgValue is an event-specific value.
// \param pvMsgData is an event-specific pointer.
//
// This function is called by the bulk driver to notify us of any events
// related to operation of the transmit data channel (the IN channel carrying
// data to the USB host).
//
// \return The return value is event-specific.
//
//*****************************************************************************
unsigned long TxHandler(void *pvCBData, unsigned long ulEvent,
		unsigned long ulMsgValue, void *pvMsgData) {
	return (0);
}

//*****************************************************************************
//
// This function is the call back notification function provided to the USB
// library's mass storage class.
//
//*****************************************************************************
unsigned long USBDMSCEventCallback(void *pvCBData, unsigned long ulEvent,
		unsigned long ulMsgParam, void *pvMsgData) {
	//
	// Reset the time out every time an event occurs.
	//
	g_ulIdleTimeout = USBMSC_ACTIVITY_TIMEOUT;

	switch (ulEvent) {
	//
	// Writing to the device.
	//
	case USBD_MSC_EVENT_WRITING: {
		//
		// Only update if this is a change.
		//
		if (g_eMSCState != MSC_DEV_WRITE) {
			//
			// Go to the write state.
			//
			g_eMSCState = MSC_DEV_WRITE;

		}

		break;
	}

		//
		// Reading from the device.
		//
	case USBD_MSC_EVENT_READING: {
		//
		// Only update if this is a change.
		//
		if (g_eMSCState != MSC_DEV_READ) {
			//
			// Go to the read state.
			//
			g_eMSCState = MSC_DEV_READ;

		}

		break;
	}
		//
		// The USB host has disconnected from the device.
		//
	case USB_EVENT_DISCONNECTED: {
		//
		// Go to the disconnected state.
		//
		g_eMSCState = MSC_DEV_DISCONNECTED;

		break;
	}
		//
		// The USB host has connected to the device.
		//
	case USB_EVENT_CONNECTED: {
		//
		// Go to the idle state to wait for read/writes.
		//
		g_eMSCState = MSC_DEV_IDLE;

		break;
	}
	case USBD_MSC_EVENT_IDLE:
	default: {
		break;
	}
	}

	return (0);
}

//*****************************************************************************
//
// This is the handler for this SysTick interrupt.  FatFs requires a timer tick
// every 10 ms for internal timing purposes.
//
//*****************************************************************************
void SysTickHandler(void) {
	//
	// Call the FatFs tick timer.
	//
	disk_timerproc();

	if (g_ulIdleTimeout != 0) {
		g_ulIdleTimeout--;
	}
}

void testFileRead(void){
	unsigned long ulRetcode;
	FRESULT fr;
	FIL fil;
	int var;
	unsigned int written = 0;
	unsigned short read = 0;
	unsigned char* buffer = 0;

	ulRetcode = disk_initialize(0);
	fr = f_mount(0, &FatFS);
	f_open(&fil, "0:/beep.wav", FA_READ);
//	f_open(&fil, "mpc.txt", FA_CREATE_ALWAYS | FA_WRITE);
	//fr = f_mount(0, &FatFS);
	if (fr != FR_OK ){
		return -1;
	}
	unsigned long ulSize = 100;
//	f_open(&fil, "mpc.txt", FA_CREATE_ALWAYS | FA_WRITE);
	if (WavOpen("beep.wav", wavdata) == 0) {
		WavGetFormat(wavdata, wavheader);
		read = WavRead(wavdata, buffer, 99);
	}

	//fr = f_open(&fil, "mpc.conf", FA_READ);
	if (fr == FR_OK) {
	 openConfig(&fil);
	 }
}
//*****************************************************************************
//
// This is the main loop that runs the application.
//
//*****************************************************************************

int main(void) {


	ROM_SysCtlClockSet (
			SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN
					| SYSCTL_XTAL_16MHZ);
	//
	// Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms
	// tick.
	//
	ROM_SysTickPeriodSet (ROM_SysCtlClockGet () / 100);
	ROM_SysTickEnable ();
	ROM_SysTickIntEnable ();

	//
	// Configure and enable uDMA
	//
	ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_UDMA);
	SysCtlDelay(10);
	ROM_uDMAControlBaseSet (&sDMAControlTable[0]);
	ROM_uDMAEnable ();

	//
	// Initialize the idle timeout and reset all flags.
	//
	g_ulIdleTimeout = 0;
	g_ulFlags = 0;

	//
	// Initialize the state to idle.
	//
	g_eMSCState = MSC_DEV_DISCONNECTED;

	//
	// Enable the USB controller.
	//
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);

	//
	// Set the USB pins to be controlled by the USB controller.
	//
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);

	//
	// Set the USB stack mode to Device mode with VBUS monitoring.
	//
	USBStackModeSet(0, USB_MODE_DEVICE, 0);

	//
	// Pass our device information to the USB library and place the device
	// on the bus.
	//
	USBDMSCInit(0, (tUSBDMSCDevice *)&g_sMSCDevice);


	//
	// Initialise DAC
	//
	SSIDACInit();

    //doConfig(); //this is the configuration in buttonPress.c FaultISR atm.
//	ButtonsInit(); //atm this bugs out. Check it later.
	//
	// Drop into the main loop.
	//
	unsigned short countWav;
	unsigned short read;

//	testFileRead();

	while (1) {
//		if (g_eMSCState == MSC_DEV_DISCONNECTED) { // Mass storage not connected
//													//okay to play audio
//			if (read == 0) {
//				//WavClose(wavdata);
//				WavOpen("beep.wav", wavdata);
////				WavGetFormat(wavdata, wavheader);
//				read = WavRead(wavdata, bufferWav, 99);
//			}
//			if (countWav == read) {
//				read = WavRead(wavdata, bufferWav, 99);
//				countWav = 0;
//			}
//			//f_write(&fil, buffer, 99, (WORD *)&written);
//			//f_close(&fil);
//			//SSIDACWrite(buffer[countWav], buffer[countWav + 1]);
//			countWav += 2;
//		} else if (g_eMSCState == MSC_DEV_IDLE){ // Mass storage idle, close sound files
//			WavClose(wavdata);
//			countWav = 0;
//			f_mount(1, &FatFS);
//		} else {
//			dummy = TRUE;
//			dummy != dummy /*do nothing*/;
//		}
	}
//	checkButtons();
//	PlayAudio();
}

void openConfig(FIL *fp) {
 unsigned char buffer[15];
 unsigned int read = 0;
 f_read(fp, &buffer, 15, (WORD *) read);
 }

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

